Raphael.Chart = Raphael.Chart || {};

/**
 * Draw a grid with the specified configuration (theme from the Raphael.Chart.bar.theme.grid object )
 * @params {Object} obj - we specifie the position (x,y) the steps (xstep,ystep) and the size (width,height)
 */
Raphael.fn.grid = function(obj,theme){
    // Raphael initialization
  var r = this,
    w = r.width,
    h = r.height,
    set = r.set(),
    
    // Variables Initialization
    x = obj.x || 0,
    y = obj.y || 0,
    xstep = obj.xstep || w,
    ystep = obj.ystep || h,
    width = obj.width || w,
    height = obj.height || h,
    
    // Temporary variables
    line,
    subLine;
  
  
  for(var i = 0 ; i*xstep < width ; i++){
    if(theme.animation.animateIt && i > 0){
      line = r.path("M"+(x+width/2)+" "+y+"L"+(x+width/2)+" "+(y+height)).attr(theme.lines);
      line.animate({path:"M"+(x+i*xstep)+" "+y+"L"+(x+i*xstep)+" "+(y+height)},theme.animation.ms,theme.animation.style);
    }
    else if(i > 0){
      line = r.path("M"+(x+i*xstep)+" "+y+"L"+(x+i*xstep)+" "+(y+height)).attr(theme.lines);
    }
    if(theme.interLines.display){
      for(var j = 1 ; j < 10 && i*xstep + j*(xstep/10) < width ; j++ ){
        subLine = r.path("M"+(x+ i*xstep + j*(xstep/10))+" "+y+"L"+(x + i*xstep + j*(xstep/10))+" "+(y+height)).attr(theme.interLines.style);
      }
      set.push(subLine);
    }
    set.push(line);
  }
  for(var i = 0 ; i*ystep < height ; i++){
    if(theme.animation.animateIt && i> 0){
      line = r.path("M"+x+" "+(y+height/2)+"L"+(x+width)+" "+(y+height/2)).attr(theme.lines);
      line.animate({path:"M"+x+" "+(y+height-i*ystep)+"L"+(x+width)+" "+(y+height-i*ystep)},theme.animation.ms,theme.animation.style);
    }
    else if(i > 0){
      line = r.path("M"+x+" "+(y+height-i*ystep)+"L"+(x+width)+" "+(y+height-i*ystep)).attr(theme.lines);
    }
    if(theme.interLines.display){
      for(var j = 1 ; j < 10 && height-i*ystep - j*(ystep/10) > 0 ; j++ ){
        subLine = r.path("M"+x+" "+(y+height-i*ystep - j*(ystep/10))+"L"+(x+width)+" "+(y+height-i*ystep- j*(ystep/10))).attr(theme.interLines.style);
      }
      set.push(subLine);
    }
    set.push(line);
  }
  return set;
};

/**
 * Draw an axis width a specified theme
 * @param {Object} obj - the configuration of the axis we must specifie the position (x,y) and the size (width).
 * @param {Object} theme - the theme of axis.
 */
Raphael.fn.axis = function(obj,theme){
    // Raphael initialization
  var r = this,
    w = r.width,
    h = r.height,
    set = r.set(),
    rotate = obj.rotate ||0,
    arrow1,
    arrow2,
    line;
    
  if(theme.arrow.display){
    if(theme.arrow.double){
      arrow1 = r.arrow({x:obj.x-theme.arrow.width,y:obj.y,width:theme.arrow.width,height:theme.arrow.height}).attr(theme.arrow.style).rotate(180+rotate,obj.x,obj.y);
      line = r.path("M"+(obj.x+theme.arrow.width)+","+obj.y+"L"+(obj.x+obj.width-theme.arrow.width)+","+obj.y).attr(theme.line).rotate(rotate,obj.x,obj.y);
      arrow2 = r.arrow({x:obj.x+obj.width-theme.arrow.width,y:obj.y,width:theme.arrow.width,height:theme.arrow.height}).attr(theme.arrow.style).rotate(rotate,obj.x,obj.y);
      set.push(arrow1,arrow2,line);
    }
    else{
      line = r.path("M"+obj.x+","+obj.y+"L"+(obj.x+obj.width-theme.arrow.width)+","+obj.y).attr(theme.line);
      arrow1 = r.arrow({x:obj.x+obj.width-theme.arrow.width,y:obj.y,width:theme.arrow.width,height:theme.arrow.height}).attr(theme.arrow.style);
      set.push(line,arrow1).rotate(rotate,obj.x,obj.y);
    }
  }
  else{
    line = r.path("M"+obj.x+","+obj.y+"L"+(obj.x+obj.width)+","+obj.y).attr(theme.line);
    set.push(line).rotate(rotate,obj.x,obj.y);
  }
  return set;
};

/**
 * Draw the background
 * @param {Object} obj - The theme of the background.
 */
Raphael.fn.background = function (obj){
  var r = this;
    set = r.set(),
    type = obj.type || "color",
    color = obj.color || "#fff";
  switch(type){
    case "color" : 
      backColor(color);
      break;
    case "image" :
      backImage( obj["img-src"] , obj["img-type"] );
      break;
  }
  return set;
  
  // Functions
  
  function backColor(color){
    var rectangle = r.rect(0,0,r.width,r.height,10).attr({fill : color});
    set.push(rectangle);
  }
  
  function backImage(imgsrc,imgtype){
    
    var image = $('#'+imgsrc),
      h = 0,
      w = 0,
      img;
    h = image.attr("height");
    w = image.attr("width");
    if(h==0 || w==0){
          alert("Enable to load the image !");
          return;
        }
    switch(imgtype){
      case "fill" : 
        img = r.image(image.attr("src"),0,0,r.width,r.height);
        set.push(img);
        break;
      case "tile" :
        for(var i  = 0 ; i < (r.width/w) ; i++){
          for(var j  = 0 ; j < (r.height/h) ; j++){
            img = r.image(image.attr("src"),i*w,j*h,w,h);
            set.push(img);
          }
        }
        break;
      default :
        img = r.image(image.attr("src"),(r.width-w)/2,(r.height-h)/2,w,h);
        set.push(img);
        break;
    }
  }
}

/**
 * Draw a transparent rectangle
 * @param {Object} obj - the configuration of the rectangle, we must specifie the position (x,y) or the offsets (xoffset,yoffset), and the size (width,height).
 * @param {Object} theme - the theme of axis. The color and the opacity
 */
Raphael.fn.transparentRect = function(obj,theme){
  var r = this,
    w = r.width,
    h = r.height,
    set = r.set(),
    x = obj.x || 0,
    y = obj.y || 0,
    xoff = obj.xoffset || false,
    yoff = obj.yoffset || false,
    width = obj.width || w,
    height = obj.height || h,
    color = theme.color,
    op = theme.opacity,
    radius = theme.radius || 0,
    rect;
    
  if(xoff || yoff){
    if(xoff==false)
      xoff = 0;
    if(yoff==false)
      yoff = 0;
    rect = r.rect(xoff,yoff,w-2*xoff,h-2*yoff,radius).attr({fill:color,opacity:op});
  }
  else{
    rect = r.rect(x,y,width,height,radius).attr({fill:color,opacity:op,stroke:"none"});
  }
  set.push(rect);
  return set;
}

Raphael.fn.triangle = function(obj){
  return this.path("M"+obj.x1+","+obj.y1+"L"+obj.x2+","+obj.y2+"L"+obj.x3+","+obj.y3+"L"+obj.x1+","+obj.y1);
}

function sector(cx, cy, r1,r2, startAngle, endAngle) {
      var rad = Math.PI / 180,
          x0 = cx + r1 * Math.cos(-startAngle * rad),
          x1 = cx + r2 * Math.cos(-startAngle * rad),
          x2 = cx + r2 * Math.cos(-endAngle * rad),
          x3 = cx + r1 * Math.cos(-endAngle * rad),
          y0 = cy + r1 * Math.sin(-startAngle * rad),
          y1 = cy + r2 * Math.sin(-startAngle * rad),
          y2 = cy + r2 * Math.sin(-endAngle * rad),
          y3 = cy + r1 * Math.sin(-endAngle * rad),
          res = ["M", x0, y0, "L", x1, y1, "A", r2, r2, 1, +(Math.abs(endAngle - startAngle) > 180), 0, x2, y2, "L", x3, y3, "A", r1, r1, 0, +(Math.abs(+startAngle - endAngle) > 180), 1,x0,y0].join(",");
      return res;
}

Raphael.fn.arrow = function(obj){
  return this.triangle({x1:obj.x,x2:obj.x,x3:obj.x+obj.width,y1:obj.y-obj.height/2,y2:obj.y+obj.height/2,y3:obj.y}).attr({stroke : "none"});
}

Raphael.fn.toolTip = function(obj,theme){
  var r = this,
      set = r.set();
  var rect = r.rect(obj.cx-obj.width/2,obj.cy-obj.height/2,obj.width,obj.height,obj.radius).attr(theme.style);
  var title = r.text(obj.cx,obj.cy-obj.height/4).attr(theme.text.title);
  var msg = r.text(obj.cx,obj.cy+obj.height/4).attr(theme.text.message);
  
  set.animateTo = function(cx,cy,theme){
    rect.animate({x : cx-obj.width/2, y : cy-obj.height/2},1000,">").attr(theme.style);
    title.animate({x:cx,y:cy-obj.height/4},1000,">").attr(theme.text.title);
    msg.animate({x:cx,y:cy+obj.height/4},1000,">").attr(theme.text.message);
    return set;
  };
  
  set.push(rect,title,msg);
  return set;
};

Raphael.fn.legendary = function(labels,values,obj,theme){
  var r = this,
      set = r.set(),
      
      // Variables :
      width = obj.width,
      height = obj.height,
      x = obj.x,
      y = obj.y,
      
      // Temporary variables :
      len = labels.length,
      deltaY = height/len,
      yoffset = 1,
      xoffset = 10,
      rectW = 50;
  
  // Public variables :
      set.legend = [];
      set.text = [];
      set.vals = [];
  
  // Display the background
  if(theme.background.display){
    var bg = r.rect(0,0,width,height).attr(theme.background.style);
    set.push(bg);
  }
  
  for(var i = 0 ; i<len ; i++){
    set.legend[i] = r.rect(2,i*deltaY+yoffset,rectW,deltaY-2*yoffset).attr($.extend({},theme.colors[i],{stroke:"none"}));
    set.text[i] = r.text(2 + rectW + xoffset , (i+1/2) * deltaY , labels[i]).attr($.extend({},theme.textStyle,{"text-anchor":"start"}));
    set.vals[i] = r.text(width - 2 , (i+1/2) * deltaY , " : "+values[i]).attr($.extend({},theme.textStyle,{"text-anchor":"end"}));
    set.push(set.legend[i],set.text[i],set.vals[i]);
  }
  
  if(theme.draggable){
    var start = function () {
        // storing original coordinates
        bg.ox = bg.attr("x");
        bg.oy = bg.attr("y");
        for(var i = 0 ; i<len ; i++){
          set.text[i].ox = set.text[i].attr("x");
          set.text[i].oy = set.text[i].attr("y");
          set.vals[i].ox = set.vals[i].attr("x");
          set.vals[i].oy = set.vals[i].attr("y");
          set.legend[i].ox = set.legend[i].attr("x");
          set.legend[i].oy = set.legend[i].attr("y");
        }
    },
    move = function (dx, dy) {
        // move will be called with dx and dy
        bg.attr({x: bg.ox + dx, y: bg.oy + dy});
        for(var i = 0 ; i<len ; i++){
          set.text[i].attr({x: set.text[i].ox + dx, y: set.text[i].oy + dy});
          set.vals[i].attr({x: set.vals[i].ox + dx, y: set.vals[i].oy + dy});
          set.legend[i].attr({x: set.legend[i].ox + dx, y: set.legend[i].oy + dy});
        }
    },
    up = function () {

    };

    set.drag(move,start,up);
    
  }
  
  set.translate(x,y);
  
  return set;
}

Raphael.fn.regularPolygon = function(x,y,radius,n){
  var r = this,
      tab = ["M",x+radius,y],
      angle = 0,
      line;
  for(var i = 1 ; i<n ; i++){
    angle+=360/n;
    tab.push("L",x+radius*Math.cos(Raphael.rad(angle)),y-radius*Math.sin(Raphael.rad(angle)));
  }
  tab.push("z");
  line = r.path().attr({path:tab.join(',')});
  
  line.isPoint = "true";
  line.x = x;
  line.y = y;
  return line;
};

validExtension = function(path,extension){
    var ext = path.substr(path.lastIndexOf('.'));
    for(var i = 0; i < extension.length; i++) {
      if(ext == extension[i]) { 
        return true
      } 
    }
    return false;
};

Array.prototype.sum = function(){
  for(var i=0,sum=0;i<this.length;sum+=this[i++]);
  return sum;
}